#include "VertexManager.h"
#include "LineManager.h"

CVertexManager::CVertexManager(CLineManager* pLManager)
{
	m_lVertex.clear();
	m_lKnots.clear();
	m_pLManager = pLManager;
}

CVertexManager::~CVertexManager()
{
	m_lVertex.clear();
	m_lKnots.clear();
	m_pLManager = NULL;
}

bool CVertexManager::AddVertex(CVertex v)
{
	CVertexIter it;
	v.Clip();
	for (it = m_lVertex.begin(); it != m_lVertex.end(); it++)
		if (*it == v)
			return false;
	m_lVertex.push_front(v);
	CVertex* pV = FindVertex(v);
	//	modify pLManager;
	//	for scaffold, nothing changes
	//	for line segment, we have to find all lines which come across the vertex, and split them into two
	CLineSegmentIter lineIt;
	for (lineIt = m_pLManager->m_lSegment.begin(); lineIt != m_pLManager->m_lSegment.end(); lineIt++)
	{
		if (IsInLineSegment(v.m_v3D, *lineIt))
		{
			//	we have to split the line into two
			CLineSegment newLine;
			newLine.m_start = pV;
			newLine.m_end = lineIt->m_end;
			lineIt->m_end = pV;
			m_pLManager->m_lSegment.push_front(newLine);
		}
	}
	return true;
}

bool CVertexManager::DeleteVertex(CVertex v)
{
	CVertex* pV = FindVertex(v);
	if (!pV)
		return false;
	//	modify pLManager
	//	what can we delete?
	//	TODO
	m_lVertex.remove(v);
	return true;
}

void CVertexManager::AddVertexFromHead(CVertex v)
{
	m_lVertex.push_front(v);
}

bool CVertexManager::DeleteVertexFromHead()
{
	if (m_lVertex.size() == 0)
		return false;
	m_lVertex.pop_front();
	return true;
}

bool CVertexManager::AddKnot(CVertex v)
{
	CVertexIter it;
	for (it = m_lKnots.begin(); it != m_lKnots.end(); it++)
	{
		if (*it == v)
			return false;
	}
	m_lKnots.push_front(v);
	return true;
}

bool CVertexManager::DeleteKnot(CVertex v)
{
	//	TODO
	return true;
}

CVertex* CVertexManager::FindVertex(CVertex v)
{
	CVertexIter it;
	for (it = m_lVertex.begin(); it != m_lVertex.end(); it++)
		if (*it == v)
			return &(*it);
	return NULL;
}

CVertex* CVertexManager::FindKnot(CVertex v)
{
	CVertexIter it;
	for (it = m_lKnots.begin(); it != m_lKnots.end(); it++)
		if (*it == v)
			return &(*it);
	return NULL;
}

CVertex* CVertexManager::FindNearest2DVertex(CVertex2D v2D)
{
	CVertexIter it = m_lVertex.begin();
	float minDist = CalcDistance(it->m_v2D, v2D);
	float dist;
	CVertex* pV = &(*it);
	it++;
	for (; it != m_lVertex.end(); it++)
	{
		if ((dist = CalcDistance(it->m_v2D, v2D)) < minDist)
		{
			minDist = dist;
			pV = &(*it);
		}
	}
	return pV;
}

CVertex* CVertexManager::FindNearest3DVertex(CVertex3D v3D)
{
	CVertexIter it = m_lVertex.begin();
	float minDist = CalcDistance(it->m_v3D, v3D);
	float dist;
	CVertex* pV = &(*it);
	it++;
	for (; it != m_lVertex.end(); it++)
	{
		if ((dist = CalcDistance(it->m_v3D, v3D)) < minDist)
		{
			minDist = dist;
			pV = &(*it);
		}
	}
	return pV;
}

int CVertexManager::GetVertexCount()
{
	return m_lVertex.size();
}

int CVertexManager::GetVertexCountWithoutInfPoint()
{
	CVertexIter it;
	int count = 0;
	for (it = m_lVertex.begin(); it != m_lVertex.end(); it++)
	{
		if (abs(it->m_v3D.m_data[0]) != SKE_INF_POINT
			&& abs(it->m_v3D.m_data[1]) != SKE_INF_POINT
			&& abs(it->m_v3D.m_data[2]) != SKE_INF_POINT)
		{
			count++;
		}
	}
	return count;
}

CVertex* CVertexManager::GetVertex(int index)
{
	int count = GetVertexCount();
	index = (index >= 0) ? index : 0;
	index = (index < count) ? index : count - 1;
	int temp = 0;
	CVertexIter it;
	for (it = m_lVertex.begin(); it != m_lVertex.end(); it++, temp++)
	{
		if (temp == index)
			return &(*it);
	}
	return NULL;
}

int CVertexManager::GetKnotCount()
{
	return m_lKnots.size();
}

CVertex* CVertexManager::GetKnot(int index)
{
	int count = GetKnotCount();
	index = (index > 0) ? index : 0;
	index = (index < count) ? index : count - 1;
	int temp = 0;
	CVertexIter it;
	for (it = m_lKnots.begin(); it != m_lKnots.end(); it++, temp++)
	{
		if (temp == index)
			return &(*it);
	}
	return NULL;
}